#include "VisualizationExporter.h"
#include <filesystem>
#include <iostream>
#include <sstream>

VisualizationExporter::VisualizationExporter(const std::string& output_dir, const std::string& case_name)
    : output_dir_(output_dir), case_name_(case_name) {
    ensureDirectoryExists();
}

void VisualizationExporter::addParetoSolution(const ParetoSolution& solution) {
    pareto_solutions_.push_back(solution);
}

void VisualizationExporter::logMemoryAllocation(int step, int cache_type, int buf_id, 
                                               int start_addr, int size, const std::string& op) {
    memory_allocations_.push_back({step, cache_type, buf_id, start_addr, size, op});
}

void VisualizationExporter::logMemoryStats(int step, int cache_type, double usage, 
                                          int free_blocks, int max_free_size) {
    memory_stats_.push_back({step, cache_type, usage, free_blocks, max_free_size});
}

void VisualizationExporter::addBufferLifetime(const BufferLifetime& lifetime) {
    buffer_lifetimes_.push_back(lifetime);
}

void VisualizationExporter::logConvergence(int iter, double best_time, double best_spill, double diversity) {
    convergence_data_.push_back({iter, best_time, best_spill, diversity});
}

void VisualizationExporter::exportParetoFront() {
    std::string filepath = getFilePath("pareto_solutions.csv");
    std::ofstream file(filepath);
    
    if (!file.is_open()) {
        std::cerr << "Cannot open file: " << filepath << std::endl;
        return;
    }
    
    // 写入表头
    file << "solution_id,time,spill,strategy_type,min_farthest_use_threshold,w_use,w_vol,w_vic\n";
    
    // 写入数据
    for (const auto& sol : pareto_solutions_) {
        file << sol.solution_id << ","
             << std::fixed << std::setprecision(2) << sol.time << ","
             << sol.spill << ","
             << sol.strategy_type << ","
             << sol.params.min_farthest_use_threshold << ","
             << sol.params.w_use << ","
             << sol.params.w_vol << ","
             << sol.params.w_vic << "\n";
    }
    
    file.close();
    std::cout << "Pareto front data exported: " << filepath << std::endl;
}

void VisualizationExporter::exportMemoryAllocations() {
    std::string filepath = getFilePath("memory_allocation_history.csv");
    std::ofstream file(filepath);
    
    if (!file.is_open()) {
        std::cerr << "Cannot open file: " << filepath << std::endl;
        return;
    }
    
    // 写入表头
    file << "step,cache_type,buffer_id,start_addr,size,operation\n";
    
    // 写入数据
    for (const auto& alloc : memory_allocations_) {
        file << alloc.step << ","
             << alloc.cache_type << ","
             << alloc.buffer_id << ","
             << alloc.start_addr << ","
             << alloc.size << ","
             << alloc.operation << "\n";
    }
    
    file.close();
    std::cout << "Memory allocation history exported: " << filepath << std::endl;
}

void VisualizationExporter::exportMemoryStats() {
    std::string filepath = getFilePath("memory_usage_stats.csv");
    std::ofstream file(filepath);
    
    if (!file.is_open()) {
        std::cerr << "Cannot open file: " << filepath << std::endl;
        return;
    }
    
    // 写入表头
    file << "step,cache_type,usage_percent,num_free_blocks,max_free_block_size\n";
    
    // 写入数据
    for (const auto& stat : memory_stats_) {
        file << stat.step << ","
             << stat.cache_type << ","
             << std::fixed << std::setprecision(2) << stat.usage_percent << ","
             << stat.num_free_blocks << ","
             << stat.max_free_block_size << "\n";
    }
    
    file.close();
    std::cout << "Memory usage stats exported: " << filepath << std::endl;
}

void VisualizationExporter::exportBufferLifetimes() {
    std::string filepath = getFilePath("buffer_lifetimes.csv");
    std::ofstream file(filepath);
    
    if (!file.is_open()) {
        std::cerr << "Cannot open file: " << filepath << std::endl;
        return;
    }
    
    // 写入表头
    file << "buffer_id,start_step,end_step,cache_type,size\n";
    
    // 写入数据
    for (const auto& lifetime : buffer_lifetimes_) {
        file << lifetime.buffer_id << ","
             << lifetime.start_step << ","
             << lifetime.end_step << ","
             << lifetime.cache_type << ","
             << lifetime.size << "\n";
    }
    
    file.close();
    std::cout << "Buffer lifetimes exported: " << filepath << std::endl;
}

void VisualizationExporter::exportConvergenceData() {
    std::string filepath = getFilePath("convergence_history.csv");
    std::ofstream file(filepath);
    
    if (!file.is_open()) {
        std::cerr << "Cannot open file: " << filepath << std::endl;
        return;
    }
    
    // 写入表头
    file << "iteration,best_time,best_spill,population_diversity\n";
    
    // 写入数据
    for (const auto& conv : convergence_data_) {
        file << conv.iteration << ","
             << std::fixed << std::setprecision(2) << conv.best_time << ","
             << conv.best_spill << ","
             << conv.population_diversity << "\n";
    }
    
    file.close();
    std::cout << "Convergence history exported: " << filepath << std::endl;
}

void VisualizationExporter::exportAllData() {
    std::cout << "=== Starting visualization data export ===" << std::endl;
    exportParetoFront();
    exportMemoryAllocations();
    exportMemoryStats();
    exportBufferLifetimes();
    exportConvergenceData();
    std::cout << "=== Visualization data export completed ===" << std::endl;
}

std::string VisualizationExporter::getFilePath(const std::string& filename) {
    return output_dir_ + "/" + case_name_ + "_" + filename;
}

void VisualizationExporter::ensureDirectoryExists() {
    try {
        std::filesystem::create_directories(output_dir_);
    } catch (const std::exception& e) {
        std::cerr << "Cannot create directory " << output_dir_ << ": " << e.what() << std::endl;
    }
}
